package pkg

import (
	"bytes"
	"errors"
	"fmt"
	"gitee.com/eqyun/gosdk/sdk"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
	"io/ioutil"
	"log"
	"net/http"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	TrafficKey = "X-Request-Id"
	LoggerKey  = "_go-admin-logger-request"
)

func HttpReadResponse(resp *http.Response, err error) (string, error) {
	defer func() {
		recover()
		if resp != nil {
			resp.Body.Close()
		}
	}()
	if err != nil {
		return "", err
	}
	contentByte, err2 := ioutil.ReadAll(resp.Body)
	if err2 != nil {
		return "", err2
	}
	return string(contentByte), nil
}
func CompareHashAndPassword(e string, p string) (bool, error) {
	err := bcrypt.CompareHashAndPassword([]byte(e), []byte(p))
	if err != nil {
		return false, err
	}
	return true, nil
}

// HasError 错误断言
// 当 error 不为 nil 时触发 panic
// 对于当前请求不会再执行接下来的代码，并且返回指定格式的错误信息和错误码
// 若 msg 为空，则默认为 error 中的内容
func HasError(err error, msg string, code ...int) {
	if err != nil {
		statusCode := 200
		if len(code) > 0 {
			statusCode = code[0]
		}
		if msg == "" {
			msg = err.Error()
		}
		_, file, line, _ := runtime.Caller(1)
		log.Printf("%s:%v error: %#v", file, line, err)
		panic("CustomError#" + strconv.Itoa(statusCode) + "#" + msg)
	}
}

// GenerateMsgIDFromContext 生成msgID
func GenerateMsgIDFromContext(c *gin.Context) string {
	requestId := c.GetHeader(TrafficKey)
	if requestId == "" {
		requestId = uuid.New().String()
		c.Header(TrafficKey, requestId)
	}
	return requestId
}

// GetOrm 获取orm连接
func GetOrm(c *gin.Context) (*gorm.DB, error) {
	idb, exist := c.Get("db")
	if !exist {
		return nil, errors.New("db connect not exist")
	}
	switch idb.(type) {
	case *gorm.DB:
		//新增操作
		return idb.(*gorm.DB), nil
	default:
		return nil, errors.New("db connect not exist")
	}
}

func DoTaskAfterSec(task func(), sec int) {
	if sec <= 0 {
		sec = 1
	}
	go func() {
		defer func() {
			e := recover()
			if e != nil {
				task()
			}
		}()
		ticker := time.NewTicker(time.Duration(sec) * time.Second)
		<-ticker.C
		task()
		ticker.Stop()
	}()
}

func PrintlnLog(a ...interface{}) {
	sdk.Runtime.GetLogger().Info(a...)
	/*f, err := os.OpenFile("D:\\wordspace\\go\\src\\makerich\\log.txt",
		os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		//log.Println(err)
	}
	defer f.Close()
	w := bufio.NewWriter(f)
	// Use Fprint to write things to the file.
	// ... No trailing newline is inserted.
	fmt.Fprintln(w, time.Now().Format("2006-01-02 15:04:05"), a)
	fmt.Println(time.Now().Format("2006-01-02 15:04:05"), a)
	w.Flush()*/
}
func Decimal(num float64) float64 {
	num, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", num), 64)
	return num
}

// GetFirstDateOfWeek 获取本周周一的日期
func GetFirstDateOfWeek(t time.Time) time.Time {
	offset := int(time.Monday - t.Weekday())
	if offset > 0 {
		offset = -6
	}
	return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local).
		AddDate(0, 0, offset)
}

func GetFirstDateOfMonth(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.Local)
}
func GetDatePlusDay(t time.Time, day int) time.Time {
	return t.Add(time.Duration(day*24) * time.Hour)
}

// GetNextFirstDateOfWeek 获取下周周一
func GetNextFirstDateOfWeek(t time.Time) time.Time {
	return GetFirstDateOfWeek(t).
		AddDate(0, 0, 7)
}

// GetLastDateOfWeek 获取本周周日
func GetLastDateOfWeek(t time.Time) time.Time {

	return GetFirstDateOfWeek(t).
		AddDate(0, 0, 6)

}

// GetLastWeekFirstDate 获取上周的周一日期
func GetLastWeekFirstDate(t time.Time) time.Time {
	thisWeekMonday := GetFirstDateOfWeek(t)

	return thisWeekMonday.AddDate(0, 0, -7)
}

// GetLastWeekLastDate 获取下周周日
func GetLastWeekLastDate(t time.Time) time.Time {
	return GetLastDateOfWeek(t).AddDate(0, 0, -7)
}

var MyClient = http.DefaultClient

func HttpGetJsonWithHeader(url string, headerStr string) (resp *http.Response, err error) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	h := strings.Split(headerStr, "\n")
	for _, s := range h {
		if len(s) == 0 {
			continue
		}
		ss := strings.Split(s, ": ")
		request.Header.Add(ss[0], ss[1])
	}
	//client := http.Client{}
	request.Close = true
	return MyClient.Do(request)
}

func HttpPostJsonWithHeader(url string, headerStr string, jsonStr string) (resp *http.Response, err error) {
	bytesData := []byte(jsonStr)
	reader := bytes.NewReader(bytesData)
	request, err := http.NewRequest("POST", url, reader)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")

	h := strings.Split(headerStr, "\n")
	for _, s := range h {
		if len(s) == 0 {
			continue
		}
		ss := strings.Split(s, ": ")
		request.Header.Add(ss[0], ss[1])
	}
	//client := http.Client{}
	request.Close = true
	return MyClient.Do(request)
}
